package f.h.dragon.patterns.money;

import junit.framework.TestCase;

/**
 * MoneyTest: money test
 * 
 * @author Wenlong Meng(wenlong.meng@gmail.com)
 * @version 1.0 at 2012/04/21
 * @since 1.0
 */
public class MoneyTest extends TestCase {

	//local variables
	private Money f12CHF;
	private Money f14CHF;
	private Money f7USD;
	private Money f21USD;

	private IMoney fMB1;
	private IMoney fMB2;

	/**
	 * @param args
	 */
	public static void main(String args[]) {
		junit.textui.TestRunner.run(MoneyTest.class);
	}

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() {
		f12CHF = new Money(12, "CHF");
		f14CHF = new Money(14, "CHF");
		f7USD = new Money(7, "USD");
		f21USD = new Money(21, "USD");

		fMB1 = MoneyBag.create(f12CHF, f7USD);
		fMB2 = MoneyBag.create(f14CHF, f21USD);
	}

	/**
	 * test money-bag multiply
	 */
	public void testBagMultiply() {
		// {[12 CHF][7 USD]} *2 == {[24 CHF][14 USD]}
		IMoney expected = MoneyBag.create(new Money(24, "CHF"), new Money(14, "USD"));
		assertEquals(expected, fMB1.multiply(2));
		assertEquals(fMB1, fMB1.multiply(1));
		assertTrue(fMB1.multiply(0).isZero());
	}

	/**
	 * test money-bag negate
	 */
	public void testBagNegate() {
		// {[12 CHF][7 USD]} negate == {[-12 CHF][-7 USD]}
		IMoney expected = MoneyBag.create(new Money(-12, "CHF"), new Money(-7, "USD"));
		assertEquals(expected, fMB1.negate());
	}

	/**
	 * test money-bag add
	 */
	public void testBagSimpleAdd() {
		// {[12 CHF][7 USD]} + [14 CHF] == {[26 CHF][7 USD]}
		IMoney expected = MoneyBag.create(new Money(26, "CHF"), new Money(7, "USD"));
		assertEquals(expected, fMB1.add(f14CHF));
	}

	/**
	 * test money-bag subtract
	 */
	public void testBagSubtract() {
		// {[12 CHF][7 USD]} - {[14 CHF][21 USD] == {[-2 CHF][-14 USD]}
		IMoney expected = MoneyBag.create(new Money(-2, "CHF"), new Money(-14, "USD"));
		assertEquals(expected, fMB1.subtract(fMB2));
	}

	/**
	 * test money-bag add
	 */
	public void testBagSumAdd() {
		// {[12 CHF][7 USD]} + {[14 CHF][21 USD]} == {[26 CHF][28 USD]}
		IMoney expected = MoneyBag.create(new Money(26, "CHF"), new Money(28, "USD"));
		assertEquals(expected, fMB1.add(fMB2));
	}

	/**
	 * test isZero
	 */
	public void testIsZero() {
		assertTrue(fMB1.subtract(fMB1).isZero());
		assertTrue(MoneyBag.create(new Money(0, "CHF"), new Money(0, "USD")).isZero());
	}

	/**
	 * test Mixed Simple Add
	 */
	public void testMixedSimpleAdd() {
		// [12 CHF] + [7 USD] == {[12 CHF][7 USD]}
		IMoney expected = MoneyBag.create(f12CHF, f7USD);
		assertEquals(expected, f12CHF.add(f7USD));
	}

	/**
	 * test Bag NotEquals
	 */
	public void testBagNotEquals() {
		IMoney bag = MoneyBag.create(f12CHF, f7USD);
		assertFalse(bag.equals(new Money(12, "DEM").add(f7USD)));
	}

	/**
	 * test MoneyBag Equals
	 */
	public void testMoneyBagEquals() {
		assertTrue(!fMB1.equals(null));
		assertEquals(fMB1, fMB1);
		IMoney equal = MoneyBag.create(new Money(12, "CHF"), new Money(7, "USD"));
		assertTrue(fMB1.equals(equal));
		assertTrue(!fMB1.equals(f12CHF));
		assertTrue(!f12CHF.equals(fMB1));
		assertTrue(!fMB1.equals(fMB2));
	}

	/**
	 * test MoneyBag Hash
	 */
	public void testMoneyBagHash() {
		IMoney equal = MoneyBag.create(new Money(12, "CHF"), new Money(7, "USD"));
		assertEquals(fMB1.hashCode(), equal.hashCode());
	}

	/**
	 * test Money Equals
	 */
	public void testMoneyEquals() {
		assertTrue(!f12CHF.equals(null));
		Money equalMoney = new Money(12, "CHF");
		assertEquals(f12CHF, f12CHF);
		assertEquals(f12CHF, equalMoney);
		assertEquals(f12CHF.hashCode(), equalMoney.hashCode());
		assertTrue(!f12CHF.equals(f14CHF));
	}

	/**
	 * test Money Hash
	 */
	public void testMoneyHash() {
		assertTrue(!f12CHF.equals(null));
		Money equal = new Money(12, "CHF");
		assertEquals(f12CHF.hashCode(), equal.hashCode());
	}

	/**
	 * test Simplify
	 */
	public void testSimplify() {
		IMoney money = MoneyBag.create(new Money(26, "CHF"), new Money(28, "CHF"));
		assertEquals(new Money(54, "CHF"), money);
	}

	/**
	 * test Normalize2
	 */
	public void testNormalize2() {
		// {[12 CHF][7 USD]} - [12 CHF] == [7 USD]
		Money expected = new Money(7, "USD");
		assertEquals(expected, fMB1.subtract(f12CHF));
	}

	/**
	 * test Normalize3
	 */
	public void testNormalize3() {
		// {[12 CHF][7 USD]} - {[12 CHF][3 USD]} == [4 USD]
		IMoney ms1 = MoneyBag.create(new Money(12, "CHF"), new Money(3, "USD"));
		Money expected = new Money(4, "USD");
		assertEquals(expected, fMB1.subtract(ms1));
	}

	/**
	 * test Normalize4
	 */
	public void testNormalize4() {
		// [12 CHF] - {[12 CHF][3 USD]} == [-3 USD]
		IMoney ms1 = MoneyBag.create(new Money(12, "CHF"), new Money(3, "USD"));
		Money expected = new Money(-3, "USD");
		assertEquals(expected, f12CHF.subtract(ms1));
	}

	/**
	 * test Print
	 */
	public void testPrint() {
		assertEquals("[12 CHF]", f12CHF.toString());
	}

	/**
	 * test Simple Add
	 */
	public void testSimpleAdd() {
		// [12 CHF] + [14 CHF] == [26 CHF]
		Money expected = new Money(26, "CHF");
		assertEquals(expected, f12CHF.add(f14CHF));
	}

	public void testSimpleBagAdd() {
		// [14 CHF] + {[12 CHF][7 USD]} == {[26 CHF][7 USD]}

		IMoney expected = MoneyBag.create(new Money(26, "CHF"), new Money(7,
				"USD"));
		assertEquals(expected, f14CHF.add(fMB1));
	}

	/**
	 * test Simple Multiply
	 */
	public void testSimpleMultiply() {
		// [14 CHF] *2 == [28 CHF]
		Money expected = new Money(28, "CHF");
		assertEquals(expected, f14CHF.multiply(2));
	}

	/**
	 * test Simple Negate
	 */
	public void testSimpleNegate() {
		// [14 CHF] negate == [-14 CHF]
		Money expected = new Money(-14, "CHF");
		assertEquals(expected, f14CHF.negate());
	}

	/**
	 * test Simple Subtract
	 */
	public void testSimpleSubtract() {
		// [14 CHF] - [12 CHF] == [2 CHF]
		Money expected = new Money(2, "CHF");
		assertEquals(expected, f14CHF.subtract(f12CHF));
	}

}
